package com.yu.mall.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yu.mall.configuration.WxConfig;
import com.yu.mall.constants.Constants;
import com.yu.mall.dto.BaseDTO;
import com.yu.mall.entity.User;
import com.yu.mall.entity.White;
import com.yu.mall.mapStruct.user.UserChange;
import com.yu.mall.mapper.UserMapper;
import com.yu.mall.service.PayService;
import com.yu.mall.service.WhiteService;
import com.yu.mall.util.PasswordUtil;
import com.yu.mall.util.RedisUtil;
import com.yu.mall.util.ResultUtils;
import com.yu.mall.util.WechatPayUtil;
import com.yu.mall.vo.ResultMessage;
import com.yu.mall.vo.ResultVO;
import com.yu.mall.vo.user.UserVO;
import com.yu.mall.vo.wx.WxLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Objects;

@RequestMapping("wx")
@RestController
@Api(tags = "微信管理", value = "微信管理")
@Slf4j
public class WxController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserChange userChange;

    @Autowired
    PayService payService;

    @Autowired
    private WhiteService whiteService;

    @Autowired
    private RedisUtil redisUtil;

    @PostMapping(value="login")
    @ApiImplicitParam(name = "code",value="code",required=true)
    public ResultVO<UserVO> login(HttpServletRequest request, String code) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        String url = wxConfig.getLoginUrl();
        url = url.replace("APPID",wxConfig.getAppid());
        url = url.replace("JSCODE",code);
        url = url.replace("SECRET",wxConfig.getSecret());
        log.info("请求微信获取openid参数："+ url);
        String vo =  restTemplate.getForObject(url, String.class);
        log.info("请求微信获取openid参数返回："+ vo);
        WxLoginVO wxLoginVO = JSON.parseObject(vo, WxLoginVO.class);
        if(Constants.WX_RESULT_CODE != wxLoginVO.getErrcode()){
            return ResultUtils.error("请求失败");
        }
/*        WxLoginVO wxLoginVO = new WxLoginVO();
        wxLoginVO.setOpenid("1");
        wxLoginVO.setSession_key("yangyu");*/
        User user = userMapper.selectByPrimaryKey(wxLoginVO.getOpenid());
        if(Objects.isNull(user)){
            user = new User();
            user.setOpenid(wxLoginVO.getOpenid());
            user.setUnionid(wxLoginVO.getUnionid());
            user.setCreateTime(new Date());
            userMapper.insertSelective(user);
        }
        UserVO userVO = userChange.toVo(user);
        String key = wxLoginVO.getSession_key();
        String token = PasswordUtil.encode3Des(PasswordUtil.KEY, wxLoginVO.getSession_key());
        redisUtil.set(key,JSON.toJSONString(user),60*60*24);
        if(StringUtils.isNotBlank(user.getPhone())){
            userVO.setToken(token);
        }
        if(StringUtils.isNotBlank(userVO.getPhone())){
            White white = whiteService.selectByPrimaryKey(userVO.getPhone());
            if(Objects.nonNull(white)){
                userVO.setIsCard("0");
            }
        }
        return ResultUtils.success(userVO);
    }

    @PostMapping(value="payNotify")
    @ApiOperation(value = "微信支付回调")
    public String payNotify(HttpServletRequest request){
        try {
            String reqData = WechatPayUtil.getReqData(request);
            log.info("微信支付回调，原文：{}",reqData);
            JSONObject decryptData = getDecryptData(reqData);
            log.info("微信支付回调，解密数据：{}",decryptData);
            boolean flag = payService.handlePayNotify(decryptData);
            if(flag){
                return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
            }
        } catch (Exception e) {
            log.error("处理微信支付回调失败",e);
        }
        return "{\"code\":\"FAIL\",\"message\":\"失败\"}";
    }

    @PostMapping(value="refundNotify")
    @ApiOperation(value = "微信退款回调")
    public String refundNotify(HttpServletRequest request){
        return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
        /*try {
            String reqData = WechatPayUtil.getReqData(request);
            log.info("微信退款回调，原文：{}",reqData);
            JSONObject decryptData = getDecryptData(reqData);
            log.info("微信退款回调，解密数据：{}",decryptData);
            boolean flag = payService.handleRefundNotify(decryptData);
            if(flag){
                return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
            }
        } catch (Exception e) {
            log.error("处理微信退款回调失败",e);
        }
        return "{\"code\":\"FAIL\",\"message\":\"失败\"}";*/
    }

    private JSONObject getDecryptData(String reqData) throws Exception{
        JSONObject reqDataJson = JSON.parseObject(reqData);
        JSONObject resource = reqDataJson.getJSONObject("resource");
        String associatedData = resource.getString("associated_data");
        String nonce = resource.getString("nonce");
        String ciphertext = resource.getString("ciphertext");
        String decryptDataStr = WechatPayUtil.decryptToString(associatedData.getBytes("UTF-8"),
                nonce.getBytes("UTF-8"), ciphertext);
        JSONObject decryptData = JSON.parseObject(decryptDataStr);
        return decryptData;
    }

    @PostMapping("pay")
    @ApiOperation(value = "支付")
    @ApiImplicitParam(name = "orderNo",value="订单编号")
    public ResultVO<JSONObject> pay(BaseDTO dto,String orderNo,String payType) {
        ResultMessage<JSONObject> result = payService.createPay(orderNo,orderNo,dto.getOpenid(),payType, "测试支付");
        if(!result.getResult()){
            return ResultUtils.error(result.getMsg());
        }
        return ResultUtils.success(result.getData());
    }
}
